:file:D:\桌面\wuliu11\src\views\delivery\routes\History.vue
<template>
  <div class="history-container">
    <el-card class="history-card">
      <!-- 标题和筛选区域 -->
      <div class="header">
        <h2>历史路线记录</h2>
        <div class="filter-area">
          <el-date-picker
              v-model="dateRange"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              value-format="YYYY-MM-DD"
          />
          <el-input
              v-model="searchKeyword"
              placeholder="搜索起点/终点地址"
              clearable
              class="search-input"
          />
          <el-button type="primary" @click="loadHistory">查询</el-button>
        </div>
      </div>
      <div class="tip">
        <el-alert title="数据来自本地存储的导航记录" type="info" :closable="false" />
      </div>

      <!-- 历史记录表格 -->
      <el-table :data="historyList" stripe style="width: 100%" v-loading="loading">
        <el-table-column prop="date" label="日期" width="120" sortable>
          <template #default="{ row }">
            {{ formatDate(row.startTime) }}
          </template>
        </el-table-column>
        <el-table-column prop="startPoint" label="起点" min-width="180">
          <template #default="{ row }">
            <div class="location-cell">
              <span class="location-icon">📍</span>
              {{ row.startAddress || `${row.startLng}, ${row.startLat}` }}
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="endPoint" label="终点" min-width="180">
          <template #default="{ row }">
            <div class="location-cell">
              <span class="location-icon">🏁</span>
              {{ row.endAddress || `${row.endLng}, ${row.endLat}` }}
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="distance" label="距离(米)" width="120" align="center">
          <template #default="{ row }">
            {{ row.distance.toFixed(2) }}
          </template>
        </el-table-column>
        <el-table-column prop="duration" label="耗时(分钟)" width="120" align="center">
          <template #default="{ row }">
            {{ row.duration }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="150" align="center">
          <template #default="{ row }">
            <el-button size="small" @click="showRouteOnMap(row)">查看路线</el-button>
            <el-button size="small" type="danger" @click="deleteRecord(row.id)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页控件 -->
      <div class="pagination">
        <el-pagination
            v-model:current-page="pagination.currentPage"
            v-model:page-size="pagination.pageSize"
            :total="pagination.total"
            layout="total, prev, pager, next, jumper"
            @current-change="loadHistory"
        />
      </div>
    </el-card>

    <!-- 地图预览弹窗 -->
    <el-dialog v-model="mapDialogVisible" title="历史路线预览" width="80%">
      <div class="map-preview">
        <div id="history-map" style="height: 500px;"></div>
        <div class="route-info">
          <p><strong>日期：</strong>{{ formatDate(selectedRoute.startTime) }}</p>
          <p><strong>起点：</strong>{{ selectedRoute.startAddress }}</p>
          <p><strong>终点：</strong>{{ selectedRoute.endAddress }}</p>
          <p><strong>距离：</strong>{{ selectedRoute.distance.toFixed(2) }} 米</p>
          <p><strong>耗时：</strong>{{ selectedRoute.duration }} 分钟</p>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'

// 历史记录数据
const historyList = ref([])
const loading = ref(false)
const dateRange = ref([])
const searchKeyword = ref('')
const mapDialogVisible = ref(false)
const selectedRoute = ref({})
let historyMap = null

// 分页配置
const pagination = ref({
  currentPage: 1,
  pageSize: 10,
  total: 0
})

// 格式化日期
const formatDate = (timestamp) => {
  if (!timestamp) return ''
  const date = new Date(timestamp)
  return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`
}

// 加载历史记录（添加筛选功能）
const loadHistory = async () => {
  loading.value = true
  try {
    // 从本地存储加载所有数据
    const allHistory = JSON.parse(localStorage.getItem('navigationHistory') || '[]')

    // 应用筛选条件
    let filteredData = [...allHistory]

    // 日期范围筛选
    if (dateRange.value && dateRange.value.length === 2) {
      const [startDate, endDate] = dateRange.value
      const startTimestamp = new Date(startDate).getTime()
      const endTimestamp = new Date(endDate).getTime() + 24 * 60 * 60 * 1000 // 包含结束日期的全天

      filteredData = filteredData.filter(item => {
        return item.startTime >= startTimestamp && item.startTime < endTimestamp
      })
    }

    // 关键词筛选
    if (searchKeyword.value) {
      const keyword = searchKeyword.value.toLowerCase()
      filteredData = filteredData.filter(item => {
        return (
            (item.startAddress && item.startAddress.toLowerCase().includes(keyword)) ||
            (item.endAddress && item.endAddress.toLowerCase().includes(keyword))
        )
      })
    }

    // 分页处理
    pagination.value.total = filteredData.length
    const startIndex = (pagination.value.currentPage - 1) * pagination.value.pageSize
    const endIndex = startIndex + pagination.value.pageSize

    // 按时间倒序排列（最新在前）
    historyList.value = filteredData
        .sort((a, b) => b.startTime - a.startTime)
        .slice(startIndex, endIndex)

  } catch (error) {
    console.error('加载历史记录失败:', error)
    ElMessage.error('加载历史记录失败: ' + error.message)
  } finally {
    loading.value = false
  }
}

// 在地图上显示路线
const showRouteOnMap = (route) => {
  selectedRoute.value = route
  mapDialogVisible.value = true

  nextTick(() => {
    if (!historyMap) {
      historyMap = new AMap.Map('history-map', {
        zoom: 13,
        center: [route.startLng, route.startLat]
      })
    } else {
      historyMap.clearMap()
    }

    // 添加起点终点标记
    const startMarker = new AMap.Marker({
      position: [route.startLng, route.startLat],
      content: '<div class="marker">📍</div>'
    })

    const endMarker = new AMap.Marker({
      position: [route.endLng, route.endLat],
      content: '<div class="marker">🏁</div>'
    })

    historyMap.add([startMarker, endMarker])

    // 绘制实际路线
    if (route.pathPoints && route.pathPoints.length > 0) {
      const polyline = new AMap.Polyline({
        path: route.pathPoints,
        strokeColor: "#3366FF",
        strokeWeight: 5,
        strokeStyle: "solid"
      })
      historyMap.add(polyline)
      historyMap.setFitView()
    } else {
      // 如果没有详细路线数据，绘制直线
      const line = new AMap.Polyline({
        path: [
          [route.startLng, route.startLat],
          [route.endLng, route.endLat]
        ],
        strokeColor: '#3366FF',
        strokeWeight: 5
      })
      historyMap.add(line)
      historyMap.setFitView()
    }
  })
}
// 添加路线步骤标记
const addRouteMarkers = (steps) => {
  steps.forEach((step, index) => {
    // 在每个步骤的第一个点添加标记
    if (step.path.length > 0) {
      const marker = new AMap.Marker({
        position: step.path[0],
        content: `<div style="
          background: white;
          border: 2px solid #3366FF;
          border-radius: 50%;
          width: 20px;
          height: 20px;
          display: flex;
          justify-content: center;
          align-items: center;
          font-weight: bold;
        ">${index + 1}</div>`
      })
      historyMap.add(marker)

      // 添加信息窗口
      const infoWindow = new AMap.InfoWindow({
        content: `<div style="min-width:200px">
          <h4>步骤 ${index + 1}</h4>
          <p>${step.instruction}</p>
          <p>距离: ${step.distance}米 | 时间: ${Math.round(step.time / 60)}分钟</p>
        </div>`,
        offset: new AMap.Pixel(0, -30)
      })

      // 点击标记显示信息窗口
      marker.on('click', () => {
        infoWindow.open(historyMap, marker.getPosition())
      })
    }
  })
}
// 删除记录
const deleteRecord = (id) => {
  ElMessageBox.confirm('确定删除这条历史记录吗？', '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    try {
      // 从本地存储加载
      const historyData = JSON.parse(localStorage.getItem('navigationHistory') || '[]')

      // 过滤掉要删除的记录
      const newHistory = historyData.filter(item => item.id !== id)

      // 保存回本地存储
      localStorage.setItem('navigationHistory', JSON.stringify(newHistory))

      ElMessage.success('删除成功')
      loadHistory()
    } catch (error) {
      ElMessage.error('删除失败: ' + error.message)
    }
  }).catch(() => {})
}

onMounted(() => {
  loadHistory()
})


















</script>

<style scoped>
.history-container {
  padding: 20px;
  height: calc(100vh - 60px);
}

.history-card {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding-bottom: 15px;
  border-bottom: 1px solid #eee;
}

.filter-area {
  display: flex;
  gap: 10px;
}

.search-input {
  width: 300px;
}

.location-cell {
  display: flex;
  align-items: center;
  gap: 8px;
}

.location-icon {
  font-size: 16px;
}

.pagination {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}

.map-preview {
  display: flex;
  gap: 20px;
}

#history-map {
  flex: 1;
  border-radius: 8px;
  overflow: hidden;
}

.route-info {
  width: 300px;
  padding: 15px;
  background: #f5f7fa;
  border-radius: 8px;
}

.route-info p {
  margin: 10px 0;
  font-size: 14px;
}
、
/* 添加筛选区域响应式优化 */
@media (max-width: 992px) {
  .filter-area {
    flex-direction: column;
    align-items: flex-start;
  }

  .search-input {
    width: 100%;
    margin: 10px 0;
  }
}

/* 优化表格样式 */
.location-cell {
  padding: 8px 0;
}

.el-table .cell {
  padding: 8px 12px;
}


</style>
